package com.common.zrd.validation.support;


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.Charset;

class Native2AsciiConvertInputStream
        extends InputStream {
    private static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");
    private static final String PREFIX = "\\u";
    private final Object lock;
    private final BufferedReader lineInputStream;
    private byte[] readBytes;
    private int currentPosition = 0;

    Native2AsciiConvertInputStream(InputStream inputStream, Charset cs) {
        this.lineInputStream = new BufferedReader(new InputStreamReader(inputStream, cs == null ? DEFAULT_CHARSET : cs));
        this.lock = this;
    }

    private static String native2Ascii(String str) {
        StringBuilder sb = new StringBuilder();
        for (char c : str.toCharArray()) {
            sb.append(char2Ascii(c));
        }
        return sb.toString();
    }

    private static String char2Ascii(char c) {
        if (c > '?') {
            StringBuilder sb = new StringBuilder();
            sb.append("\\u");

            int code = c >> '\b';
            String tmp = Integer.toHexString(code);
            if (tmp.length() == 1) {
                sb.append("0");
            }
            sb.append(tmp);

            code = c & 0xFF;
            tmp = Integer.toHexString(code);
            if (tmp.length() == 1) {
                sb.append("0");
            }
            sb.append(tmp);
            return sb.toString();
        }
        return Character.toString(c);
    }

    @Override
    public int read()
            throws IOException {
        synchronized (this.lock) {
            if ((this.readBytes == null) &&
                    (readBytes())) {
                return -1;
            }
            if ((this.currentPosition == this.readBytes.length) &&
                    (readBytes())) {
                return -1;
            }
            byte read = this.readBytes[this.currentPosition];
            this.currentPosition += 1;
            return read;
        }
    }

    private boolean readBytes()
            throws IOException {
        String currentReaderLine = this.lineInputStream.readLine();
        if (currentReaderLine == null) {
            return true;
        }
        byte[] bytes = native2Ascii(currentReaderLine).getBytes();
        this.readBytes = new byte[bytes.length + 2];
        System.arraycopy(bytes, 0, this.readBytes, 0, bytes.length);
        this.readBytes[bytes.length] = 13;
        this.readBytes[(bytes.length + 1)] = 10;
        this.currentPosition = 0;
        return false;
    }

    @Override
    public void close()
            throws IOException {
        synchronized (this.lock) {
            this.lineInputStream.close();
        }
    }
}
